package it.patamau.bukkit;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Properties;

import org.bukkit.plugin.Plugin;
import org.bukkit.plugin.PluginDescriptionFile;

/**
 * Used to map class fields directly into a property file
 */
public abstract class PluginParameters {
	
	public static final String VERSION = "0.1";
	
	public final String pluginVersion;
	public final String pluginName;
	
	private final String comment;
	private String propertiesFile;
	
	public PluginParameters(Plugin plugin){
        PluginDescriptionFile pdf = plugin.getDescription();
        if(pdf!=null){
	        pluginVersion = pdf.getVersion();
	        pluginName = pdf.getName();
        }else{
        	pluginVersion = "0.1";
        	pluginName = plugin.getClass().getSimpleName();
        }
    	propertiesFile = pluginName+".properties";
    	comment = pluginName+" "+pluginVersion;
	}
	
	/**
	 * Load the default properties file (name.properties)
	 * @throws IOException
	 */
	public final void load() throws IOException{
		load(propertiesFile);
	}
	
	/**
	 * Store to the default properties file (name.properties)
	 * @throws IOException
	 */
	public final void store() throws IOException{
		store(propertiesFile);
	}
	
	public final ArrayList<Field> getAffectedFields(){
		ArrayList<Field> fields = new ArrayList<Field>();
		for(Field f: this.getClass().getFields()){
			if(Modifier.isFinal(f.getModifiers())||
					Modifier.isProtected(f.getModifiers())||
					Modifier.isPrivate(f.getModifiers())||
					Modifier.isStatic(f.getModifiers())||
					Modifier.isTransient(f.getModifiers())){
				continue;
			}
			fields.add(f);
		}
		return fields;
	}
	
	/**
	 * Stores the fields of the current class to the given filename
	 * @param filename
	 * @throws IOException
	 */
	public final void store(String filename) throws IOException{
		Properties ps = new Properties();
		
		for(Field f: getAffectedFields()){
			try{
				Object o = f.get(this);
				if(o!=null){
					ps.setProperty(f.getName(), o.toString());
				}
			}catch(IllegalArgumentException e){
				e.printStackTrace();
			} catch (IllegalAccessException e) {
				e.printStackTrace();
			}
		}
		FileOutputStream fos = new FileOutputStream(filename);
		ps.store(fos,comment);
		fos.close();
	}
	
	/**
	 * Loads the properties from the given filename
	 * @param filename
	 * @throws IOException 
	 */
	public final void load(String filename) throws IOException{
		Properties ps = new Properties();
		FileInputStream fis = new FileInputStream(filename);
		ps.load(fis);
		fis.close();
		
		for(Field f: getAffectedFields()){
			String p = ps.getProperty(f.getName());
			if(p!=null){
				try{
					Class<?> t = f.getType();
					if(t == Integer.TYPE){
						f.set(this, Integer.parseInt(p));
					}else if(t == Boolean.TYPE){
						f.set(this, Boolean.parseBoolean(p));
					}else if(t == Long.TYPE){
						f.set(this, Long.parseLong(p));
					}else if(t == Float.TYPE){
						f.set(this, Float.parseFloat(p));
					}else if(t == String.class){
						f.set(this, p);
					}else{
						throw new IllegalArgumentException(t.getSimpleName());
					}
				} catch (NumberFormatException e){
					e.printStackTrace();
				} catch (IllegalArgumentException e) {
					e.printStackTrace();
				} catch (IllegalAccessException e) {
					e.printStackTrace();
				}
			}
		}
	}
}
